﻿namespace CgSilverlightDynamicGeometry
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using CgSilverlightDynamicGeometry.Utilities;

    public class CartesianLabels
    {
        List<TextBlock> Labels = new List<TextBlock>();

        private Drawing drawing;

        public Drawing Drawing
        {
            get { return drawing; }
            set
            {
                if (drawing == value)
                {
                    return;
                }
                drawing = value;
            }
        }

        public void UpdateVisual()
        {
            CoordinateSystem coordinateSystem = Drawing.CoordinateSystem;
            var xPoints = coordinateSystem.GetVisibleXPoints();
            var yPoints = coordinateSystem.GetVisibleYPoints();

            int count = xPoints.Count() + yPoints.Count();
            if (Labels.Count<count)
            {
                AddNewLabels(count - Labels.Count);
            }
            else if (Labels.Count>count)
            {
                RemoveExcessLabels(Labels.Count - count);
            }

            int i = 0;
            foreach (var x in xPoints)
            {
                MoveLabelX(Labels[i++], x, coordinateSystem);
            }
            foreach (var y in yPoints)
            {
                MoveLabelY(Labels[i++], y, coordinateSystem);
            }
        }

        /// <summary>
        /// 添加文本
        /// </summary>
        /// <param name="count">数量</param>
        private void AddNewLabels(int count)
        {
            for (int i = 0; i < count; i++)
            {
                var newLabel = new TextBlock();
                newLabel.Foreground = new SolidColorBrush(Color.FromArgb(255, 128, 128, 255));
                newLabel.SetZIndex((int)ZOrder.Cartesian);
                Labels.Add(newLabel);
                Drawing.Canvas.Children.Add(newLabel);
            }
        }

        /// <summary>
        /// 移除
        /// </summary>
        /// <param name="count">数量</param>
        private void RemoveExcessLabels(int count)
        {
            for (int i = Labels.Count-count; i < Labels.Count; i++)
            {
                Drawing.Canvas.Children.Remove(Labels[i]);
            }
            Labels.RemoveRange(Labels.Count - count, count);
        }

        /// <summary>
        /// 绘制X文本
        /// </summary>
        /// <param name="label">绘制的文本</param>
        /// <param name="x">X方向移动量</param>
        /// <param name="coordinateSystem"></param>
        private void MoveLabelX(TextBlock label, double x, CoordinateSystem coordinateSystem)
        {
            SetLabelText(label, x);
            var coordinates = coordinateSystem
                .ToPhysical(new Point(x, 0));
            MoveLabel(label, coordinates);
        }

        /// <summary>
        /// 绘制Y文本
        /// </summary>
        /// <param name="label">绘制的文本</param>
        /// <param name="y">Y方向移动量</param>
        /// <param name="coordinateSystem"></param>
        private void MoveLabelY(TextBlock label, double y, CoordinateSystem coordinateSystem)
        {
            SetLabelText(label, y);
            var coordinates = coordinateSystem
                .ToPhysical(new Point(0, y));
            MoveLabel(label, coordinates);
        }

        private void SetLabelText(TextBlock label, double x)
        {
            string text = x.ToString(CultureInfo.InvariantCulture);
            if (label.Text!=text)
            {
                label.Text = text;
            }
        }

        private void MoveLabel(TextBlock label, Point coordinates)
        {
            Point old = label.GetCoordinates();
            if (old!=coordinates)
            {
                label.MoveTo(coordinates);
            }
        }
    }
}
